type ClassDecoratorFunction = (target: (...args: any) => any, context: ClassMethodDecoratorContext) => void;

/**
 * @description invoke on after define
 * @type {ClassDecoratorFunction}
 * @param {{() => void}} target - in here, it is m method.
 * @param {ClassMethodDecoratorContext<C, (this: C, ...args: []) => void>} context
 * @returns {void}
 */
const bound: ClassDecoratorFunction = (target: { (): void; }, context: ClassMethodDecoratorContext<C, (this: C, ...args: []) => void>): void => {
  console.log("value", target);
  console.log("context", context);

  if (context.private) throw new TypeError("Not supported on private methods.");
  context.addInitializer(function () {
    this[context.name] = this[context.name].bind(this);
  });
};

class C {
  message = "Hello";

  @bound
  m() {
    console.log(this.message);
  }
}
